#include "threelevelconditiondetect.h"

void ThreeLevelNormalDetectStrategy::execute(NormalDetectBase & NormalDetectBase, SteelInfo *steel, int level)
{

    foreach (ClientDefect *defect, steel->ClientDefect1ist){
        DefectLvDetectWrapper* conditionInfoList =  NormalDetectBase.findDefectByName(defect->getDefectName(),steel->getSteelType());
        if(conditionInfoList){
            int cond_Length = conditionInfoList->findElementByName("三级")->GetLength();
            int cond_width = conditionInfoList->findElementByName("三级")->GetWidth();
            if(defect->getWidth() >= cond_width && defect->getHeight() >= cond_Length){
                defect->SetDefectLevel(level);
                steel->AddToThreeLevelMap(defect->getDefectName());
            }
        }
    }

    //统计3级该条件下的数量
    for (auto it = steel->ThreeLvDefectMap.begin(); it !=  steel->ThreeLvDefectMap.end(); ++it) {
        // qDebug() << "Key:" << it.key() << ", Value:" << it.value();
        if(auto condtion = NormalDetectBase.findDefectByName(it.key(),steel->getSteelType())){

            if(it.value() > condtion->findElementByName("三级")->GetTimes()){
                QString info = QString("%4: 缺陷: %1 数量过多%2(%3),该卷被判定为:3 ").arg(it.key()).arg(it.value()).arg(condtion->findElementByName("三级")->GetTimes()).arg(steel->getSteelName());
                steel->infos.append(info);
                steel->setLevel(level);
                qDebug()<<info;
            }
        }
    }
}

void ThreeLevelBesideDetectStrategy::execute(NormalDetectBase & NormalDetectBase, SteelInfo *steel, int level)
{
    foreach (ClientDefect *defect, steel->ClientDefect1ist) {
         if(DefectLvDetectWrapper* conditionInfoList =  NormalDetectBase.findDefectByName(defect->getDefectName(),steel->getSteelType())){
            if( defect->getLeftinSteel() > conditionInfoList->findElementByName("三级")->GetLength()
                || defect->getRightintSteel() > conditionInfoList->findElementByName("三级")->GetLength() ){
                defect->SetDefectLevel(level);
                steel->setLevel(level);
                steel->AddToThreeLevelMap(defect->getDefectName());
                QString info = QString(" %1 : 缺陷: %2 数量超过设定的边部阈值,该卷被判定为:3").arg(steel->getSteelName()).arg(defect->getDefectName());
                steel->infos.append(info);
                qDebug()<<info;
             }

         }
    }
}


void ThreeLevelFrequencyDetectStrategy::execute(NormalDetectBase & NormalDetectBase, SteelInfo *steel, int level)
{
    //存储各个相机需要做频率判断的缺陷：不需要对每个相同的缺陷进行重复的判断 只需要对不同的缺陷进行对比

    // 频率的统计 只分上下表面
    QList<ClientDefect*> TopSurface;
    QList<ClientDefect*> BottomSurface;

    foreach (ClientDefect *defect, steel->ClientDefect1ist) {
        if(DefectLvDetectWrapper* conditionInfoList =  NormalDetectBase.findDefectByName(defect->getDefectName(),steel->getSteelType())){
            if(defect->getCameraNo() <= 2){
                TopSurface.append(defect);
            }else{
                BottomSurface.append(defect);;
            }
        }
    }
    if (TopSurface.size()> 0){
        calculateFrequence(TopSurface,NormalDetectBase,steel,level,true);
    }

    if (BottomSurface.size()> 0) {
        calculateFrequence(BottomSurface,NormalDetectBase,steel,level,false);
    }



}

double ThreeLevelFrequencyDetectStrategy::calculateDistance(const ClientDefect &d1, const ClientDefect &d2) const
{
    //在二维空间中的欧几里得距离：两点之间的直线距离
    double dx = abs(d1.getLeftinSteel() - d2.getLeftinSteel());
    double dy = abs(d1.getTopinSteel() - d2.getTopinSteel());
    return std::sqrt(dx * dx + dy * dy);
     // return std::sqrt(std::pow(d1.getLeftinSteel() - d2.getLeftinSteel(), 2) + std::pow(d1.getRightintSteel() - d2.getRightintSteel(), 2));
}

void ThreeLevelFrequencyDetectStrategy::calculateFrequence(QList<ClientDefect *> list, NormalDetectBase &NormalDetectBase, SteelInfo *steel, int level, bool isTop)
{
    //缺陷名称,该缺陷出现的次数
    //容器中的当前缺陷其他的每一个去进行对比
    for (int i = 0; i < list.size(); ++i) {
        int totalCount = 0;
        int reqLength = NormalDetectBase.findDefectByName(list[i]->getDefectName(),steel->getSteelType())->findElementByName("三级")->GetLength();
        int reqFrenquence = NormalDetectBase.findDefectByName(list[i]->getDefectName(),steel->getSteelType())->findElementByName("三级")->GetTimes();
        //缺陷率
        int defectRatio = NormalDetectBase.findDefectByName(list[i]->getDefectName(),steel->getSteelType())->findElementByName("三级")->GetWidth();

        int TotalDefectLength = list[i]->getHeight(); //满足条件的缺陷总长

        for (int j = 0; j < list.size(); ++j) {
            //忽略第一个
            if(i!=j && list[i]->getDefectName() == list[j]->getDefectName()){
                double distance = calculateDistance(*list[i],*list[j]);
                if(distance <= reqLength ){
                    totalCount += 1;
                    TotalDefectLength += list[j]->getHeight();
                }
            }
        }
        //如果频率超过了并且 总长也超过了就降级
        if(totalCount >= reqFrenquence){
            //需要有需要计算缺陷率的缺陷 那么额外附加计算缺陷率
            qDebug()<<"缺陷出现多处正在进行缺陷率的检测。。。。";
            if( defectRatio > 0 ){
                //算缺陷率
                float actualLength = steel->getTopLen() * (defectRatio / 100.0);
                float Templength = 0.0;//获取该表面下这个缺陷的总长是否超过指定的缺陷率长度
                foreach (ClientDefect *defect, list) {
                    Templength+=defect->getHeight();
                }
                if( Templength > actualLength){
                    QString str = QString(" %1 : 缺陷: %2 在:%3 超过设定的频率数量%4(%5),并且缺陷率超过了 百分之(%6) 该卷被判定为:%7").arg(steel->getSteelName())
                                      .arg(list[i]->getDefectName())
                                      .arg(isTop?"上表面":"下表面")
                                      .arg(totalCount)
                                      .arg(reqFrenquence)
                                      .arg(defectRatio)
                                      .arg(level);
                    steel->AddToThreeLevelMap(list[i]->getDefectName());
                    steel->infos.append(str);
                    steel->setLevel(level);
                    qDebug()<<str;
                }
            }else{
                QString str = QString(" %1 : 缺陷: %2 在:%3 超过设定的频率数量%4(%5),该卷被判定为:%6").arg(steel->getSteelName()).arg(list[i]->getDefectName()).arg(isTop?"上表面":"下表面").arg(totalCount).arg(reqFrenquence).arg(level);
                steel->AddToThreeLevelMap(list[i]->getDefectName());
                steel->infos.append(str);
                steel->setLevel(level);
                qDebug()<<str;
            }
        }
    }
}


void ThreeLevelVerticalLengthDetectStrategy::execute(NormalDetectBase & NormalDetectBase, SteelInfo *steel, int level)
{

    //通卷率 : 一个缺陷在钢板的总体长度
    //存在缺陷长度重叠问题
    //按相机区分缺陷

    QList<ClientDefect*> cam1;
    QList<ClientDefect*> cam2;
    QList<ClientDefect*> cam3;
    QList<ClientDefect*> cam4;
    foreach (ClientDefect *defect, steel->ClientDefect1ist) {
        if(DefectLvDetectWrapper* conditionInfoList =  NormalDetectBase.findDefectByName(defect->getDefectName(),steel->getSteelType())){
            if(defect->getCameraNo() == 1){
                cam1.append(defect);
            }else if(defect->getCameraNo() == 2){
                cam2.append(defect);
            }else if(defect->getCameraNo() == 3){
                cam3.append(defect);
            }else if(defect->getCameraNo() == 4){
                cam4.append(defect);
            }else{
                continue;
            }
        }
    }
    //区分相机计长
    if (cam1.size()> 0){
        GetCounterDefectMap(cam1,NormalDetectBase,steel,level);
    }
    if (cam2.size()> 0) {
        GetCounterDefectMap(cam2,NormalDetectBase,steel,level);
    }
    if (cam3.size()> 0) {
        GetCounterDefectMap(cam3,NormalDetectBase,steel,level);
    }
    if (cam4.size()> 0) {
        GetCounterDefectMap(cam4,NormalDetectBase,steel,level);
    }

}



void ThreeLevelVerticalLengthDetectStrategy::GetCounterDefectMap(QList<ClientDefect*> cam,NormalDetectBase & NormalDetectBase,SteelInfo *steel,int lv)
{
    //将相同的缺陷放入一个容器 用于计算长度
    QMap<QString,QList<ClientDefect*>> map;

    foreach (ClientDefect *defect, cam) {
        if(map.contains(defect->getDefectName())){
            map[defect->getDefectName()].append(defect);
        }
        else
        {
            QList<ClientDefect*> temp;
            temp.append(defect);
            map.insert(defect->getDefectName(),temp);
        }
    }

    CalculateLength(map,NormalDetectBase,steel,lv);
}

void ThreeLevelVerticalLengthDetectStrategy::CalculateLength(QMap<QString, QList<ClientDefect *>> map, NormalDetectBase &NormalDetectBase, SteelInfo *steel, int lv)
{


    foreach (const QString &DefectName, map.keys()) {
        if(DefectLvDetectWrapper* conditionInfo = NormalDetectBase.findDefectByName(DefectName,steel->getSteelType())){
            int Cond_Lenth = conditionInfo->findElementByName("三级")->GetLength();
            if(map[DefectName].size() > 2 ){
                int CountLength = 0;
                for(int i = 0; i< map[DefectName].length(); ++i){
                    CountLength += map[DefectName][i]->getHeight();
                }
                float ActualLength = steel->getTopLen() * (Cond_Lenth / 100.0);
                if(CountLength >= ActualLength){
                    steel->setLevel(lv);
                    QString info = QString("%4: 缺陷: %1 超过设定的缺陷率%2(%3):,该卷被判定为:3 ").arg(DefectName).arg(ActualLength).arg(CountLength).arg(steel->getSteelName());
                    steel->infos.append(info);
                    steel->AddToThreeLevelMap(DefectName);
                    qDebug()<<info;
                }
            }
        }
    }
}

void ThreeLevelDirectDetectStrategy::execute(NormalDetectBase & NormalDetectBase, SteelInfo *steel, int level)
{
    foreach (ClientDefect *defect, steel->ClientDefect1ist) {
          if(DefectLvDetectWrapper* conditionInfoList = NormalDetectBase.findDefectByName(defect->getDefectName(), steel->getSteelType())){
            defect->SetDefectLevel(level);
            steel->setLevel(level);
            QString info = QString("%1 缺陷: %2 出现严重缺陷 改卷被判定为3").arg(steel->getSteelName()).arg(defect->getDefectName());
            steel->infos.append(info);
            steel->AddToThreeLevelMap(defect->getDefectName());
            qDebug()<<info;
          }
    }
}

